package com.fzb.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PipedInputStream;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.Socket;
import java.net.UnknownHostException;
import java.text.DecimalFormat;

public class FtpSocketUtil implements IFtpSocket, InvocationHandler {

	private Object obj;
	private FtpSession ftpSession;

	public FtpSocketUtil(Object obj,FtpSession ftpSession){
		this.obj = obj;
		this.ftpSession=ftpSession;
	}

	public FtpSocketUtil(FtpSession ftpSession) {
		this.ftpSession=ftpSession;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fzb.ftp.IFtpSocket#printOutStr()
	 */
	@Override
	public void printOutStr() {
		Socket socket;
		try {
			socket = new Socket(ftpSession.getFtpUser().getAddr(), (int)ftpSession.getAttr().get("port"));
			System.out.println(IOUtil.getStringInputStream(socket
					.getInputStream()));
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fzb.ftp.IFtpSocket#getFile(java.io.File)
	 */
	@Override
	public void getFile(final File file) {
		Socket socket;
		try {
			socket = new Socket(ftpSession.getFtpUser().getAddr(), (int)ftpSession.getAttr().get("port"));
			IOUtil.writeToFile(socket.getInputStream(), file);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.fzb.ftp.IFtpSocket#putFile(java.io.File)
	 */
	@Override
	public void putFile(final File file) {
		Socket socket;
		try {
			socket = new Socket(ftpSession.getFtpUser().getAddr(), (int)ftpSession.getAttr().get("port"));
			byte[] bytes=IOUtil.getByteByInputStream(new FileInputStream(file));
			int sendSize=0;
			int block=bytes.length/100;
			int count=bytes.length/block;
			int last=bytes.length-(100*block);
			if(block>1){
				for (int i=0;i<count;i++) {
					socket.getOutputStream().write(subByts(bytes,i*block, block));
					sendSize+=block;
					System.out.println("uploadSize "+formetFileSize(sendSize)+" -> "+((int)Math.ceil((sendSize/(bytes.length*1.00))*100))+"%");
				}
			}
			if(last!=0){
				sendSize=bytes.length;
				socket.getOutputStream().write(subByts(bytes,block*100, last));
			}
			socket.getOutputStream().close();
			socket.close();
			while(!socket.isClosed()){
				System.out.println("uploading");
			}
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static byte[] subByts(byte[] b, int start, int length) {
		byte rbytes[] = new byte[length];
		System.arraycopy(b, start, rbytes, 0, length);
		return rbytes;
	}
	
	public static String formetFileSize(long fileS) {// 转换文件大小
		DecimalFormat df = new DecimalFormat("#.00");
		String fileSizeString = "";
		if (fileS < 1024) {
			fileSizeString = df.format((double) fileS) + "B";
		} else if (fileS < 1048576) {
			fileSizeString = df.format((double) fileS / 1024) + "K";
		} else if (fileS < 1073741824) {
			fileSizeString = df.format((double) fileS / 1048576) + "M";
		} else {
			fileSizeString = df.format((double) fileS / 1073741824) + "G";
		}
		return fileSizeString;
	}
	
	@Override
	public Object invoke(final Object proxy, final Method method,
			final Object[] args) throws Throwable {
		new Thread() {
			public void run() {
				try {
					FtpReqeustImpl.lock();
					ftpSession.getAttr().put("port",0);
					ftpSession.sendMsg("PASV");
					while ((int)ftpSession.getAttr().get("port") == 0) {
						Thread.sleep(100);
					}
					method.invoke(obj, args);
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					FtpReqeustImpl.unLock();
				}
			};
		}.start();
		return null;
	}

	public static IFtpSocket getProxy(FtpSession ftpSession) {
		IFtpSocket ftpSocketUtil = new FtpSocketUtil(ftpSession);
		InvocationHandler ftpIFtpSocket = new FtpSocketUtil(ftpSocketUtil,ftpSession);
		return (IFtpSocket) Proxy.newProxyInstance(ftpIFtpSocket.getClass()
				.getClassLoader(), ftpIFtpSocket.getClass().getInterfaces(),
				ftpIFtpSocket);
	}
}
